#include "../include/clientQueue.h"
#include "../include/threadPool.h"
#include"../include/standard_library.h"
#include"../include/my_tlv.h"
#include <pthread.h>
#include <strings.h>
#include <unistd.h>


int exitPipe[2];//实现退出
void sigFunc(int signum){
    printf("signum = %d\n",signum);
    write(exitPipe[1],"1",1);
    /* printf() */ 
}



int main(int argc, char *argv[])
{

    // ./server ip port 子线程数
    ARGS_CHECK(argc, 4);
    pipe(exitPipe);
    if(fork()!=0){//父进程实现退出
        close(exitPipe[0]);//关闭读端
        signal(SIGUSR1,sigFunc);//实现优雅退出
        signal(SIGINT,sigFunc);//ctrl+C信号
        wait(NULL);//父进程等子进程退出
        exit(0);//父进程退出
    }
    threadPool_t threadPool;                    // 申请一块内存
    threadPoolInit(&threadPool, atoi(argv[3])); // 申请完了初始化一下
    // 初始完了线程池，可以创建工人线程
    makeWorker(&threadPool);
    // 初始化监听socket
    int sockfd = tcpInit(argv[1], argv[2]);
    // 创建epoll实例，将sockfd加入监听
    int epfd = epoll_create(1);                                         
    epollAdd(epfd, sockfd); // 监听请求连接
    epollAdd(epfd,exitPipe[0]);//监听退出请求
    printf("服务端启动成功，等待客户端连接\n");

    //创建客户队列并初始化
    clientQueue_t clientQueue;
    init_clientQueue(&clientQueue);

    int ret ;
    /* time_t timeStart,timeEnd; */
    while (1)
    {
        struct epoll_event readyset[1024];
        int readyNum = epoll_wait(epfd, readyset, 1024, 100);//每0.1s醒来一次

        //超时30s断开
        if(readyNum == 0){
            //超时处理    
            if(clientQueue.time_out[clientQueue.timer].size!=0){//当前时间槽中还有连接
                slotNode_t *Cur = clientQueue.time_out[clientQueue.timer].head;//拿到超时的头节点
                slotNode_t *tmp = Cur;
                int netfd;
                while(Cur!=NULL){//遍历处理超时连接
                    netfd = Cur->netfd;
                    tmp = Cur->next;
                    fdDel(netfd, &clientQueue);//把netfd从时间轮盘中删除
                    clientQueue.client[netfd] = -1;
                    epollDel(epfd, netfd);
                    close(netfd);
                    printf("超时断开连接 netfd = %d\n",netfd);
                    // send(netfd,"1",1,MSG_NOSIGNAL);//通知客户端
                    Cur = tmp;
                }
            }
            clientQueue.timer = (clientQueue.timer + 1)%TIME_SLICE;//移动到下一个时间槽
        }

        for (int i = 0; i < readyNum; i++)
        {
            if (readyset[i].data.fd == sockfd)
            {
                //有新的客户端连接
                int netfd = accept(sockfd, NULL, NULL);
                
                if (netfd < 0)
                {
                    perror("accept error");
                    continue;
                }
                fdAdd(netfd,&clientQueue);//添加到指定槽位，记录位置超时时间

                printf("有新的客户端连接，netfd = %d\n", netfd);
                // 加入任务队列并唤醒子线程
                pthread_mutex_lock(&threadPool.mutex);
                enQueue(&threadPool.taskQueue, netfd);
                pthread_cond_signal(&threadPool.cond);
                pthread_mutex_unlock(&threadPool.mutex);
            }else if(readyset[i].data.fd == exitPipe[0])//监听到退出
            {
                //全部退出，不需要关心时间片
                /* threadPool.exitFlag = 1; */  

            }
            else{//监听客户端的消息
                int netfd = readyset[i].data.fd;
                printf("netfd = %d\n",netfd);
                train_t train_get;
                bzero(&train_get,sizeof(train_get));
                ret = recv(netfd,&train_get.length,sizeof(int),0);
                if(ret ==0 ||train_get.length==0)//客户端退出，时间片处理
                {   //用户退出把对应的netfd删除
                    fdDel(netfd, &clientQueue);
                    clientQueue.client[netfd] = -1;
                    epollDel(netfd, epfd);// 从监听中去除
                    close(netfd);
                    continue;            
                }
                fdAdd(netfd,&clientQueue);//刷新客户端在时间轮的位置
            }
        }
    }

    return 0;
}

